package com.ruoyi.erecord.region.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.DataBaseHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.TreeBuildUtils;
import com.ruoyi.erecord.region.domain.Region;
import com.ruoyi.erecord.region.domain.bo.RegionBo;
import com.ruoyi.erecord.region.domain.vo.RegionVo;
import com.ruoyi.erecord.region.mapper.RegionMapper;
import com.ruoyi.erecord.region.service.IRegionService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 区域Service业务层处理
 *
 * @author cc
 * @date 2023-04-19
 */
@RequiredArgsConstructor
@Service
public class RegionServiceImpl implements IRegionService {

    private final RegionMapper baseMapper;

    /**
     * 查询区域
     */
    @Override
    public RegionVo queryById(String id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询区域列表
     */
    @Override
    public TableDataInfo<RegionVo> queryPageList(RegionBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<Region> lqw = buildQueryWrapper(bo);
        Page<RegionVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询区域列表
     */
    @Override
    public List<RegionVo> queryList(RegionBo bo) {
        LambdaQueryWrapper<Region> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<Region> buildQueryWrapper(RegionBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<Region> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getParentId()), Region::getParentId, bo.getParentId());
        lqw.eq(StringUtils.isNotBlank(bo.getTitle()), Region::getTitle, bo.getTitle());
        lqw.eq(StringUtils.isNotBlank(bo.getParentTitle()), Region::getParentTitle, bo.getParentTitle());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), Region::getStatus, bo.getStatus());
        lqw.eq(bo.getGrade() != null, Region::getGrade, bo.getGrade());

        //按树节点升序
        lqw.orderByAsc(Region::getAncestors);
        return lqw;
    }

    /**
     * 新增区域
     */
    @Override
    public Boolean insertByBo(RegionBo bo) {
        Region add = BeanUtil.toBean(bo, Region.class);
        validEntityBeforeSave(add, true);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改区域
     */
    @Override
    public Boolean updateByBo(RegionBo bo) {
        Region update = BeanUtil.toBean(bo, Region.class);
        validEntityBeforeSave(update, false);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Region entity, boolean isAdd) {
        //TODO 修改需要验证重复吗？
        if (isAdd) {
            //检查编码是否重复
            if (existsRegionCode(entity.getCode()))
                throw new ServiceException("区域编码 已经存在了！");
            //检查名称是否重复
            //            if (existsRegionName(entity.getTitle()))
            //                throw new ServiceException("区域名称 已经存在了！");
        }
        Optional<String> parentId = Optional.ofNullable(entity.getParentId());

        if (!parentId.isPresent()) {
            //            entity.setAncestors(entity.getParentId());
            return;
        }

        //不为空，查询父节点
        RegionVo pRegionVo = baseMapper.selectVoById(entity.getParentId());
        Optional<RegionVo> optionalRegionVo = Optional.ofNullable(pRegionVo);
        if (optionalRegionVo.isPresent()) {//存在
            if (!UserConstants.DEPT_NORMAL.equals(pRegionVo.getStatus())) {
                throw new ServiceException("区域停用，不允许新增");
            }
            entity.setAncestors(pRegionVo.getAncestors() + StringUtils.SEPARATOR + pRegionVo.getId());
        } else {
            entity.setAncestors(entity.getParentId());
        }


    }

    /**
     * 批量删除区域
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            long childrenSize = childrenSelectById(new ArrayList<>(ids).get(0));
            if (childrenSize > 0)
                throw new ServiceException("存在子节点，不允许删除");

        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public List<Tree<String>> treeList(RegionBo region) {
        return buildTreeSelect(this.queryList(region));
    }

    public List<Tree<String>> treeListByGrade(int grade) {
        RegionBo region = new RegionBo();
        region.setGrade(grade);
        LambdaQueryWrapper<Region> lqw = Wrappers.lambdaQuery();
        lqw.ge(true, Region::getGrade, region.getGrade());
        return buildTreeSelect(baseMapper.selectVoList(lqw));
    }

    /**
     * 查询当前节点和子节点
     *
     * @param grade 等级
     * @return value
     */
    @Override
    public List<RegionVo> listByGrade(int grade) {
        RegionBo region = new RegionBo();
        region.setGrade(grade);
        LambdaQueryWrapper<Region> lqw = Wrappers.lambdaQuery();
        lqw.ge(true, Region::getGrade, region.getGrade());
        return baseMapper.selectVoList(lqw);
    }

    public List<Tree<String>> buildTreeSelect(List<RegionVo> regionVos) {
        if (CollUtil.isEmpty(regionVos)) {
            return CollUtil.newArrayList();
        }
        return TreeBuildUtils.build(regionVos, (dept, tree) ->
            tree.setId(dept.getId())
                .setParentId(dept.getParentId())
                .setName(dept.getTitle())
                .setWeight(dept.getGrade()));
    }

    @Override
    public String getRegionNameById(String id) {
        LambdaQueryWrapper<Region> lqw = Wrappers.lambdaQuery();
        lqw.eq(Region::getId, id);
        lqw.eq(Region::getStatus, "0");
        Region record = this.baseMapper.selectOne(lqw);
        lqw.last("limit 1");
        if (null != record) {
            return record.getTitle();
        }
        return null;
    }

    @Override
    public String getRegionIdByName(String name) {
        LambdaQueryWrapper<Region> lqw = Wrappers.lambdaQuery();
        lqw.eq(Region::getTitle, name);
        lqw.eq(Region::getStatus, "0");
        Region record = this.baseMapper.selectOne(lqw);
        lqw.last("limit 1");
        if (null != record) {
            return record.getId();
        }
        return null;
    }

    @Override
    public boolean existsRegionCode(String code) {
        LambdaQueryWrapper<Region> lqw = Wrappers.lambdaQuery();
        lqw.eq(Region::getCode, code);
        lqw.eq(Region::getStatus, "0");
        return this.baseMapper.exists(lqw);
        //        Optional<Region> record = Optional.ofNullable(this.baseMapper.selectOne(lqw));

    }

    @Override
    public boolean existsRegionName(String name) {
        LambdaQueryWrapper<Region> lqw = Wrappers.lambdaQuery();
        lqw.eq(Region::getTitle, name);
        lqw.eq(Region::getStatus, "0");
        return this.baseMapper.exists(lqw);

    }

    @Override
    public long childrenSelectById(String id) {
        //        selectCount(new LambdaQueryWrapper<RegionVo>()
        //            .eq(RegionVo::getStatus, UserConstants.DEPT_NORMAL)
        //            .apply(DataBaseHelper.findInSet(id, "ancestors")));
        //        return baseMapper.selectCount(new LambdaQueryWrapper<RegionVo>().eq(RegionVo::getStatus, UserConstants.DEPT_NORMAL));
        return baseMapper.selectCount(
            new LambdaQueryWrapper<Region>()
                .eq(Region::getStatus, UserConstants.DEPT_NORMAL)
                .apply(DataBaseHelper.findInSet(id, "ancestors"))
        );
    }

}
